package com.credithc.signature.lanmaostorage.service;

import com.alibaba.fastjson.JSONObject;
import com.credithc.signature.common.utils.AmazonUtil;
import com.credithc.signature.lanmaostorage.ro.FileRo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import java.io.*;
import java.util.Map;

/**
 * @author zhanghanqiu181212@credithc.com
 * @Date 2020/6/11 16:09
 */
@Service
@Slf4j
public class FileService {
    @Value("${storage.path.cont:/data/openapi/contfile/}")
    private String contPath;
    @Value("${storage.path.image:/data/openapi/imagefile/}")
    private String imgPath;
    @Value("${storage.path.temp:/data/openapi/temp/}")
    private String contTemPath;


    public ResponseEntity<Object> storage(FileRo fileRo,String type)throws Exception {
        //根据type确定存储root路径
       // String path = getRootPath(type);

        String method = fileRo.getMethod();
        FileRo.DataObj data = fileRo.getData();
        if (StringUtils.isBlank(method)){
            return createResponseEntity("no data field in requestBody", null, HttpStatus.BAD_REQUEST);
        }
        if (StringUtils.isBlank(data.getDhash())){
            return createResponseEntity("no dhash field in requestBody.data", null, HttpStatus.BAD_REQUEST);
        }
        if (method.equals("set")){
            return saveFile(data,type);
        }else if (method.equals("get")){
            return downFile(data,type);
        }else if (method.equals("exists")){
            return existsFile(data,type);
        }else if (method.equals("del")){
            return delFile(data,type);
        }else{
            return createResponseEntity("the method " + method + " not exists", null, HttpStatus.NOT_FOUND);
        }

    }

    private String getRootPath(String type) {
        String path = contPath;
        if (type.equals("imgPath")){
            path = imgPath;
        }else if (type.equals("contTemPath")){
            path = contTemPath;
        }
        return path;
    }

    private ResponseEntity<Object> delFile(FileRo.DataObj data,String type)throws Exception {
        try {
            del(data.getDhash(),type);
        }
        catch (Throwable e) {
            throw new Exception(e.getMessage(), e);
        }
        return createResponseEntity(null);
    }
    public synchronized void del(String key,String type) throws Throwable {
        String rootPath = getRootPath(type);
        String path = getPathByKey(key, false,rootPath);
        File file = new File(path);
        if (!type.equals("contTemPath")){
            AmazonUtil.delFromS3(key);
        }
        if (!file.exists()) {
            return;
        }
        file.delete();
    }

    private ResponseEntity<Object> existsFile(FileRo.DataObj data,String type)throws Exception {
        boolean exists;
        try {
            exists=exists(data.getDhash(),type);
        }
        catch (Throwable e) {
            throw new Exception(e.getMessage(), e);
        }
        return createResponseEntity(exists ? "1" : "0");
    }

    private ResponseEntity<Object> downFile(FileRo.DataObj data,String type)throws Exception {
        byte[] fdata = null;
        try {
            fdata = get(data.getDhash(),type);
        }
        catch (Throwable e) {
            throw new Exception(e.getMessage(), e);
        }
        log.info("获取数据大小："+ fdata.length);
        return createResponseEntity(fdata);

    }

    private ResponseEntity<Object> saveFile(FileRo.DataObj data,String type)throws Exception {
        if (StringUtils.isBlank(data.getFdata())) {
            return createResponseEntity("no fdata field in requestBody.data", null, HttpStatus.BAD_REQUEST);
        }
        String base64Fdata = data.getFdata();
        byte[] fdata = Base64.decodeBase64(base64Fdata.getBytes("UTF-8"));
        if (fdata == null || fdata.length < 1) {
            return createResponseEntity("empty fdata", null, HttpStatus.BAD_REQUEST);
        }
        try {
            set(fdata, data.getDhash(),type);
            log.info("插入成功数据大小："+ fdata.length);
        }
        catch (Throwable e) {
            throw new Exception(e.getMessage(), e);
        }
        return createResponseEntity(null);
    }



    public synchronized String set(byte[] data, String key,String type) throws Throwable {
        String rootPath = getRootPath(type);
        String path = getPathByKey(key, true,rootPath);
        FileOutputStream s = null;
        try {
            s = new FileOutputStream(path);
            s.write(data);
            s.flush();
            //非临时文件上传到s3
            if (!type.equals("contTemPath")){
                File file = new File(path);
                AmazonUtil.uploadToS3(file, key);
            }
            return key;
        }
        catch (IOException e) {
            throw new RuntimeException(e);
        }
        finally {
            if (s != null) {
                try {
                    s.close();
                }
                catch (IOException e) {

                }
            }
        }
    }

    public byte[] get(String key,String type) throws Throwable {
        String rootPath = getRootPath(type);
        String path = getPathByKey(key, false,rootPath);
        File file = new File(path);
        if (!file.exists()) {
            //非临时文件 从S3上查找是否存在
            if (!type.equals("contTemPath")){
                InputStream inputStream = AmazonUtil.downFromS3(key);
                return inputStream==null?null: AmazonUtil.toByteArray(inputStream);
            }
            return null;
        }
        BufferedInputStream s = null;
        try {
            s = new BufferedInputStream(new FileInputStream(file));
            byte[] buffer = new byte[(int) file.length()];
            s.read(buffer);
            return buffer;
        }
        catch (IOException e) {
            throw new RuntimeException(e);
        }
        finally {
            if (s != null) {
                try {
                    s.close();
                }
                catch (IOException e) {

                }
            }
        }
    }


    public boolean exists(String key,String type) throws Throwable {
        String rootPath = getRootPath(type);
        String path = getPathByKey(key, false,rootPath);
        File file = new File(path);
        if (!file.exists() &&!type.equals("contTemPath")){
            String urlFromS3 = AmazonUtil.getUrlFromS3(key);
            return urlFromS3!=null;
        }
        return file.exists();
    }

    private String getPathByKey(String key, boolean createDir,String rootPath) {
        String fs = File.separator;
        String x = key.substring(key.length() - 6);
        String a = x.substring(0, 2);
        String b = x.substring(2, 4);
        String c = x.substring(4, 6);
        StringBuilder pathBuilder = new StringBuilder();
        pathBuilder.append(rootPath);
        pathBuilder.append(fs);
        pathBuilder.append(a);
        pathBuilder.append(fs);
        pathBuilder.append(b);
        pathBuilder.append(fs);
        pathBuilder.append(c);
        pathBuilder.append(fs);
        if (createDir) {
            File dir = new File(pathBuilder.toString());
            if (!dir.exists()) {
                dir.mkdirs();
            }
        }
        pathBuilder.append(key);
        return pathBuilder.toString();
    }

    //-----------------------------------------------------------------------------------------------
    protected ResponseEntity<Object> createResponseEntity() {
        JSONObject output = new JSONObject();
        return createResponseEntity(output, true, null, HttpStatus.OK);
    }

    protected ResponseEntity<Object> createResponseEntity(Object output) {
        return createResponseEntity(output, true, null, HttpStatus.OK);
    }

    protected ResponseEntity<Object> createResponseEntity(Object output, HttpStatus status) {
        return createResponseEntity(output, true, null, status);
    }

    protected ResponseEntity<Object> createResponseEntity(Object output, Map<String, String> headers, HttpStatus status) {
        return createResponseEntity(output, true, headers, status);
    }

    protected ResponseEntity<Object> createResponseEntity(Object output, boolean noCache, Map<String, String> headers, HttpStatus status) {
        HttpHeaders httpHeaders = new HttpHeaders();
        if (headers != null) {
            for (String name : headers.keySet()) {
                String value = headers.get(name);
                httpHeaders.set(name, value);
            }
        }

        if (noCache) {
            httpHeaders.set("CacheControl", "no-cache");
            httpHeaders.set("Pragma", "no-cache");
            httpHeaders.set("Expires", "-1");
        }

        if (output instanceof byte[]) {
            httpHeaders.set("Content-Length", Integer.toString(((byte[]) output).length));
        }
        else if (output instanceof String) {
            // httpHeaders.set("Content-Length", Integer.toString(((String)
            // output).length()));
        }
        else {

        }
        return new ResponseEntity<Object>(output, httpHeaders, status);
    }
}
